package com.riteny.util.qrcode;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;

public class QRCodeUtils {

    private static final String CHARSET = "utf-8";

    private static final Integer QRCODE_SIZE = 300;

    private static final String IMAGE_FORMAT = "JPG";

    /**
     * 生成二维码
     * 大小默認300px,格式為JPG
     *
     * @param content 内容
     * @param output  输出流
     * @throws Exception
     */
    public static void encode(String content, OutputStream output) throws Exception {

        encode(content, QRCODE_SIZE, IMAGE_FORMAT, output);
    }

    /**
     * 生成二维码
     * 大小默認300px
     *
     * @param content    内容
     * @param output     输出流
     * @param formatName 格式後綴
     * @throws Exception
     */
    public static void encode(String content, String formatName, OutputStream output) throws Exception {

        encode(content, QRCODE_SIZE, formatName, output);
    }

    /**
     * 生成二维码
     * 格式為JPG
     *
     * @param content    内容
     * @param qrCodeSize 二維碼尺寸
     * @param output     输出流
     * @throws Exception
     */
    public static void encode(String content, Integer qrCodeSize, OutputStream output) throws Exception {

        encode(content, qrCodeSize, IMAGE_FORMAT, output);
    }

    /**
     * 生成二维码
     *
     * @param content    内容
     * @param output     输出流
     * @param qrCodeSize 二維碼尺寸
     * @param formatName 格式後綴
     * @throws Exception
     */
    public static void encode(String content, Integer qrCodeSize, String formatName, OutputStream output) throws Exception {

        BufferedImage image = QRCodeUtils.createImage(content, qrCodeSize);

        ImageIO.write(image, formatName, output);
    }


    /**
     * 生成二维码(内嵌LOGO)
     *
     * @param content  内容
     * @param destPath 存放目录
     * @param fileName 文件名
     * @throws Exception
     */
    public static String encode(String content, String destPath, String fileName) throws Exception {

        return encode(content, QRCODE_SIZE, destPath, fileName, IMAGE_FORMAT);
    }

    public static String encode(String content, String destPath, String fileName, String formatName) throws Exception {

        return encode(content, QRCODE_SIZE, destPath, fileName, formatName);
    }

    public static String encode(String content, Integer qrCodeSize, String destPath, String fileName) throws Exception {

        return encode(content, qrCodeSize, destPath, fileName, IMAGE_FORMAT);
    }

    public static String encode(String content, Integer qrCodeSize, String destPath, String fileName, String formatName) throws Exception {

        BufferedImage image = QRCodeUtils.createImage(content, qrCodeSize);

        mkdirs(destPath);

        String file = fileName + ".jpg";
        ImageIO.write(image, formatName, new File(destPath + "/" + file));

        return file;
    }


    private static BufferedImage createImage(String content, Integer qrCodeSize) throws Exception {

        BitMatrix bitMatrix = getQrCode(content, qrCodeSize);

        return MatrixToImageWriter.toBufferedImage(bitMatrix);
    }

    /**
     * 獲取二維碼對象
     *
     * @param content    二維碼内容
     * @param qrCodeSize 二維碼尺寸
     * @return 二維碼對象
     * @throws WriterException
     */
    private static BitMatrix getQrCode(String content, Integer qrCodeSize) throws WriterException {
        return getQrCode(content, qrCodeSize, CHARSET);
    }

    /**
     * 獲取二維碼對象
     *
     * @param content    二維碼内容
     * @param qrCodeSize 二維碼尺寸
     * @return 二維碼對象
     * @throws WriterException
     */
    private static BitMatrix getQrCode(String content, Integer qrCodeSize, String charset) throws WriterException {

        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();

        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//設置容錯等級-高
        hints.put(EncodeHintType.CHARACTER_SET, charset);//設置編碼
        hints.put(EncodeHintType.MARGIN, 1);

        return new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hints);
    }

    /**
     * 当文件夹不存在时，mkdirs会自动创建多层目录，区别于mkdir．(mkdir如果父目录不存在则会抛出异常)
     *
     * @param destPath 存放目录
     * @date 2013-12-11 上午10:16:36
     */
    public static void mkdirs(String destPath) {
        File file = new File(destPath);
        //当文件夹不存在时，mkdirs会自动创建多层目录，区别于mkdir．(mkdir如果父目录不存在则会抛出异常)
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
    }
}